package googleearthdownloader;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;

import javax.swing.WindowConstants;


import java.io.OutputStream;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
/* This Class creates a JDialog containing a JTextArea.
 * You can call the public method log to add text to the JTextArea.
 * After calling log the JTextArea automatically scrolls to its last line.
 * A loglevel can be set in the constructor to filter log calls.
 * Also you can redirect System.in and System.err with hookSystemStreams option in constructor.
 */

public class SystemLog {
	
	private JScrollPane scroll;
	private JTextArea anzeige;
	private JDialog logFrame;
	private JFrame mainFrame;
	private JViewport view;
	
	private SimpleDateFormat sdf;
	private int screenHeight, screenWidth, logLevel;
	private MyPrintStream out, err;
	private boolean consoleForwarding;
	
	public static final int LOG_OFF = 0;
	public static final int LOG_INFO = 1;
	public static final int LOG_INFO_AND_DEBUG_INFO = 2;
	public static final int LOG_INFOS_AND_SHORT_ERRORMESSAGE = 3;
	public static final int LOG_FULL = 4;
	
	public static final int INFO_MESSAGE = 1;
	public static final int DEBUG_INFO_MESSAGE = 2;
	public static final int SHORT_ERROR_MESSAGE = 3;
	public static final int FULL_ERROR_MESSAGE = 4;
	
	public SystemLog(JFrame parentFrame,int logLevel, boolean hookSystemStreams, boolean consoleForwarding){
		
		mainFrame = parentFrame;
		
		this.logLevel=logLevel;
		this.consoleForwarding = consoleForwarding;
		
		sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
		
		out = new MyPrintStream(System.out);
		err = new MyPrintStream(System.err);
		
		try {
			SwingUtilities.invokeAndWait(new Runnable(){
				
				@Override
				public void run() {
					screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
					screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
					
					logFrame = new JDialog(mainFrame,"SystemLog",false);
					logFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
				
					anzeige = new JTextArea();
					anzeige.setEditable(false);
					anzeige.setLineWrap(true);
					anzeige.setWrapStyleWord(true);
					
					scroll = new JScrollPane(anzeige);
					
					view =  scroll.getViewport();
					view.setPreferredSize(new Dimension(screenWidth*10/21,screenHeight/14));
				
					logFrame.add(scroll);
					logFrame.setResizable(false);
					logFrame.setLocation(mainFrame.getLocation().x, mainFrame.getLocation().y-screenHeight*13/105);
					
					logFrame.pack();
					logFrame.setVisible(true);
					
				}
				
			});
		} catch (InterruptedException e) {
			System.out.println("InterruptedException in SystemLog initialisation");
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			System.out.println("InvocationTargetException in SystemLog initialisation");
			e.printStackTrace();
		}
		
		//Hooking System.out and System.err
		if(hookSystemStreams){
			System.setOut(out);
			System.setErr(err);
		}
		
	}
	
	public synchronized void log(String message,int logLevel){
		if(logLevel<=this.logLevel){
			if(logLevel<FULL_ERROR_MESSAGE){ //TODO maybe FullLog
				out.println(message);
			}
			else{
				err.println(message);
			}
		}
	}
	
	private void viewText(Object m){
		
		anzeige.append(sdf.format(new Date())+"  "+m.toString());
		SwingUtilities.invokeLater(new Runnable(){
			
			@Override
			public void run() {
				
				view.scrollRectToVisible(new Rectangle(new Point(0,anzeige.getHeight()-75), new Dimension(800,75)) );
			}
			
		});
	}
	
	private void viewTextLine(Object m){
		SwingUtilities.invokeLater(new outputThread(m));
	}
	
	private class outputThread extends Thread{
		
		private Object m;
		
		public outputThread(Object m){
			this.m = m;
		}
		
		@Override
		public void run() {
			anzeige.append(sdf.format(new Date())+"  "+m.toString()+"\n");
			view.scrollRectToVisible(new Rectangle(new Point(0,anzeige.getHeight()-75), new Dimension(800,75)) );
		}
	}
	
	private class MyPrintStream extends PrintStream{
		
		public MyPrintStream(OutputStream out){
			super(out);
		}
		
		
		//print
		@Override
		 public void print(boolean b){
			if(consoleForwarding){
				super.print(b);
			}
			viewText(sdf.format(new Date())+"  "+b);
		 }
         
		@Override
		 public void print(char c){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+c);
			}
			viewText(c);
		}
         
		@Override
		 public void print(char[] s){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  ");
				super.print(s);
			}
			viewText(s);
		}
          
		@Override
		 public void print(double d){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+d);
			}
			viewText(d);
		}
          
		@Override
		 public void print(float f){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+f);
			}
			viewText(f);
		}
        
		@Override
		 public void print(int i){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+i);
			}
			viewText(i);
		}
          
		@Override
		 public void print(long l){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+l);
			}
			viewText(l);
		}
         
		@Override
		 public void print(Object obj){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+obj);
			}
			viewText(obj);
		}
         
		@Override
		 public void print(String s){
			if(consoleForwarding){
				super.print(sdf.format(new Date())+"  "+s);
			}
			viewText(s);
		}
         
		
		//println
		@Override
		 public void println(){
			if(consoleForwarding){
				super.println();
			}
			viewText("");
		}
         
		@Override
		 public void println(boolean x){
			if(consoleForwarding){
				super.println(sdf.format(new Date())+"  "+x);
			}
			viewTextLine(x);
		}
         
		@Override
		 public void println(char x){
			if(consoleForwarding){
				super.println(sdf.format(new Date())+"  "+x);
			}
			
			viewTextLine(x);
		}
         
		@Override
		 public void println(char[] x){
			if(consoleForwarding){
				super.println(x);
			}
			
			viewTextLine(x);
		}
          
		@Override
		 public void println(double x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
		
		@Override
		 public void println(float x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
          
		@Override
		 public void println(int x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
        
		@Override
		 public void println(long x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
       
		@Override
		 public void println(Object x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
         
		@Override
		 public void println(String x){
			if(consoleForwarding){
				super.println(x);
			}
			viewTextLine(x);
		}
		
	}
}
